package com.chuangfeng.framework.core.dao.impl;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.transform.BasicTransformerAdapter;
import org.hibernate.transform.ResultTransformer;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.util.Assert;

import com.chuangfeng.framework.core.common.config.Constants;
import com.chuangfeng.framework.core.common.config.SystemContext;
import com.chuangfeng.framework.core.common.page.Pagination;
import com.chuangfeng.framework.core.dao.BaseDao;
import com.chuangfeng.framework.core.exception.PersistenceException;

public class SimpleBaseDaoImpl<T extends Serializable> extends BaseDaoImpl<T> implements BaseDao<T>{

protected final Logger logger = Logger.getLogger(this.getClass()); 
	

	/**
	 * 通过SQL进行分页查询
	 * 例如：SELECT NAME,SEX FROM USER 
	 * 返回：List(Map({NAME,"USER1"},{SEX,"F"}),Map({NAME,"USER2"},{SEX,"M"}),Map({NAME,"USER3"},{SEX,"F"}))
	 */
    @SuppressWarnings("unchecked")
	public List<Map> queryForList(final String queryString,final int begin, final int end){
		List<Map> result = null;
		try{
			result =  (List<Map>) getHibernateTemplate().executeWithNativeSession(
					new HibernateCallback() {
						public Object doInHibernate(Session session)
								throws HibernateException {
							if ((begin == Constants.ALL_POS)
									&& (end == Constants.ALL_POS)) {
								return session
										.createSQLQuery(queryString)
										.setResultTransformer(
												(ResultTransformer) new UpperCasedAliasToEntityMapResultTransformer())
										.list();
							} else {
								return session
										.createSQLQuery(queryString)
										.setFirstResult(begin)
										.setMaxResults(end)
										.setResultTransformer(
												(ResultTransformer) new UpperCasedAliasToEntityMapResultTransformer())
										.list();
							}
						}
					});
		}catch(Exception e){
			logger.error("查询数据错误");
			throw new PersistenceException(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 按照SQL查询所有记录
	 */
	public List<Map> queryForList(String sql){
		return queryForList(sql,Constants.ALL_POS,Constants.ALL_POS);
	}
	
	
	/**
	 * 通过SQL查询得到一个保存MAP对象的集合LIST
	 * 例如：SELECT NAME,SEX FROM USER 
	 * @param sql
	 * @param begin
	 * @param end
	 * @return
	 * @throws DBException
	 */
	public List<Map> getListBySql(String sql,int begin,int end){
		return this.queryForList(sql, begin, end);
	}
	
	/**
	 * 以系统内部设置的默认start,pagesize来查询列表
	 * @param sql
	 * @return
	 * @throws DBException
	 */
	public List<Map> getListBySql(String sql){
		return this.getListBySql(sql, SystemContext.getOffset(), SystemContext.getPagesize());
	}
	
	/**
	 * 更加SQL操作获取单一个对象，并组合成MAP返回
	 * @param sql
	 * @return
	 * @throws DBException
	 */
	
	@SuppressWarnings("unchecked")
	public Map getOneBySql(final String sql) {
		Map result =  new HashMap();
		try{
		    result = (Map) getHibernateTemplate().executeWithNativeSession(
				new HibernateCallback() {
					public Object doInHibernate(Session session)throws HibernateException {
							return session.createSQLQuery(sql)
									.setResultTransformer(
											(ResultTransformer) new UpperCasedAliasToEntityMapResultTransformer())
									.uniqueResult();
					}
				});
		}catch(Exception e){
			logger.error("查询数据错误");
			throw new PersistenceException(e.getMessage());
		}
		return result;
	}

	
	public Object queryForObject(String sql) {
		return this.uniqueResultBySQL(sql);
	}


	//来自于website的分页技术 begin
	/**
	 * 通过HQL查询以分页形式查询集合
	 */
	public Pagination searchPaginated(String hql){
		return searchPaginated(hql, null);
	}
	
	public Pagination searchPaginated(String hql,Object param){
		return searchPaginated(hql, new Object[]{param});
	}
	
	public Pagination searchPaginated(String hql,Object[] params){
		return searchPaginated(hql, params,SystemContext.getOffset(), SystemContext.getPagesize());
	}
	
	public Pagination searchPaginated(String hql,int offset,int pagesize){
		return searchPaginated(hql,null, offset, pagesize);
	}
	
	public Pagination searchPaginated(String hql,Object param,int offset,int pagesize){
		return searchPaginated(hql, new Object[]{param}, offset, pagesize);
	}
	
	@SuppressWarnings("unchecked")
	public Pagination searchPaginated(String hql,Object[] params,int offset,int pagesize){
		//获取记录总数
		String countHql = getCountQuery(hql);
		Query query = getSession().createQuery(countHql);
		if(params != null && params.length > 0){
			query = this.createQuery(countHql, params);
		}
		int total = ((Long)query.uniqueResult()).intValue();
		
		//获取结果集
		query = getSession().createQuery(hql);
		if(params != null && params.length > 0){
			query = this.createQuery(hql, params);
		}
		query.setFirstResult(offset);
		query.setMaxResults(pagesize);
		List datas = query.list();
		
		//返回Pagination
		Pagination pm = new Pagination();
		pm.setList(datas);
		pm.setTotalCount(total);
		return pm;
	}
	
	public Pagination searchPaginated(Criteria criteria) {
		return searchPaginated(criteria, SystemContext.getOffset(), SystemContext.getPagesize());
	}
	
	public Pagination searchPaginated(Criteria criteria, int offset, int pagesize) {
		Assert.notNull(criteria);
		CriteriaImpl impl = (CriteriaImpl) criteria;
		Projection projection = impl.getProjection();
		Integer totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
		criteria.setProjection(projection);
		criteria.setFirstResult(offset);
		criteria.setMaxResults(pagesize);
		List datas = criteria.list();
		//返回Pagination
		Pagination pm = new Pagination();
		pm.setList(datas);
		pm.setTotalCount(totalCount.intValue());
		return pm;
	}
	
	public void searchPaginated(Map map) {
		map.put("start", SystemContext.getOffset());
		map.put("pagesize", SystemContext.getPagesize());
	}
	
	/**
	 * 根据HQL语句，获得查询总记录数的HQL语句
	 * 如：
	 * select ... from Organization o where o.parent is null
	 * 经过转换，可以得到：
	 * select count(*) from Organziation o where o.parent is null
	 * @param hql
	 * @return
	 */
	private String getCountQuery(String hql){
		return parseCountSql(hql);
		/*
		int index = hql.indexOf("from");
		if(index != -1){
			return "select count(*) " + hql.substring(index);
		}
		throw new SystemException("无效的HQL查询语句【"+hql+"】");
		*/
	}
	
	private static class UpperCasedAliasToEntityMapResultTransformer extends BasicTransformerAdapter implements Serializable {
		@SuppressWarnings("unchecked")
		public Object transformTuple(Object[] tuple, String[] aliases) {
			Map result = new HashMap(tuple.length);
			for (int i = 0; i < tuple.length; i++) {
				String alias = aliases[i];
				if (alias != null) {
					result.put(alias.toUpperCase(), tuple[i]);
				}
			}
			return result;
		}
	}
}
